package com.dlc.shop.api.controller;

import cn.hutool.core.util.PhoneUtil;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.dlc.shop.allinpay.service.AllinpayService;
import com.dlc.shop.bean.dto.allinpay.*;
import com.dlc.shop.bean.model.UserExtension;
import com.dlc.shop.common.allinpay.constant.AllinpayConstant;
import com.dlc.shop.common.allinpay.constant.AllinpayNoticeUrl;
import com.dlc.shop.common.allinpay.member.resp.*;
import com.dlc.shop.common.response.ServerResponseEntity;
import com.dlc.shop.config.ShopConfig;
import com.dlc.shop.security.api.util.SecurityUtils;
import com.dlc.shop.security.common.util.AuthUserContext;
import com.dlc.shop.service.UserExtensionService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.AllArgsConstructor;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Objects;

/**
 * @author lanhai
 */
@Tag(name = "通联支付-会员接口(用户端)")
@RestController("appAllinpayMemberController")
@RequestMapping("/p/allinpay/member")
@AllArgsConstructor
public class AllinpayMemberController {

    private final ShopConfig shopConfig;

    private final AllinpayService allinpayService;
    private final UserExtensionService userExtensionService;

    @GetMapping("/getUserInfo")
    @Operation(summary = "获取个人会员信息", description = "获取个人会员信息")
    public ServerResponseEntity<UserInfo> getMemberInfo() {
        String bizUserId = this.getBizUserId(SecurityUtils.getUser().getUserId());
        UserInfo userInfo = allinpayService.getUserInfo(bizUserId);
        userInfo.setIdentityCardNo(null);
        userInfo.setName(null);
        // 是否默认无感绑定手机号，是则修改'是否绑定手机'为false
        if (!Objects.isNull(userInfo.getPhone())
                && Objects.equals(userInfo.getPhone(), AllinpayConstant.DEFAULT_BIND_PHONE_NUMBER)) {
            userInfo.setIsPhoneChecked(false);
        }
        userInfo.setPhone(ObjectUtils.isEmpty(userInfo.getPhone()) ? null : PhoneUtil.hideBetween(userInfo.getPhone()).toString());
        // 同时也查询用户是否绑定支付标识
        QueryBindAcctResp queryBindAcctResp = allinpayService.queryBindAcct(bizUserId);
        userInfo.setIsBindPayAcct(!CollectionUtils.isEmpty(queryBindAcctResp.getAcctInfoList()));
        return ServerResponseEntity.success(userInfo);
    }

    @PostMapping("/setRealName")
    @Operation(summary = "个人实名验证", description = "个人实名验证")
    public ServerResponseEntity<Void> setRealName(@RequestBody SetRealNameDTO setRealNameDTO) {
        // 实名认证
        String userId = SecurityUtils.getUser().getUserId();
        String bizUserId = this.getBizUserId(userId);
        allinpayService.setRealName(bizUserId, setRealNameDTO);
        // 更新用户拓展信息
        UserExtension userExtension = new UserExtension();
        userExtension.setUserId(userId);
        userExtension.setAllinpayRealNameSet(1);
        userExtensionService.updateByUserId(userExtension);
        return ServerResponseEntity.success();
    }

    @PostMapping("/setPayPwd")
    @Operation(summary = "设置支付密码", description = "设置支付密码")
    public ServerResponseEntity<String> setPayPwd(@RequestBody SetPayPwdDTO setPayPwdDTO) {
        String bizUserId = this.getBizUserId(SecurityUtils.getUser().getUserId());
        // 查询用户信息，补充用户姓名和身份证号
        UserInfo userInfo = allinpayService.getUserInfo(bizUserId);
        setPayPwdDTO.setName(userInfo.getName());
        setPayPwdDTO.setIdentityNo(userInfo.getIdentityCardNo());
        setPayPwdDTO.setPhone(userInfo.getPhone());
        String backUrl = this.getDomainUrl() + AllinpayNoticeUrl.SET_PAY_PWD;
        // 返回通联url
        String url = allinpayService.setPayPwd(bizUserId, backUrl, setPayPwdDTO);
        return ServerResponseEntity.success(url);
    }

    @PutMapping("/updatePayPwd")
    @Operation(summary = "修改支付密码", description = "修改支付密码")
    public ServerResponseEntity<String> updatePayPwd(@RequestBody SetPayPwdDTO setPayPwdDTO) {
        String bizUserId = this.getBizUserId(SecurityUtils.getUser().getUserId());
        // 查询用户信息，补充用户姓名和身份证号
        UserInfo userInfo = allinpayService.getUserInfo(bizUserId);
        setPayPwdDTO.setName(userInfo.getName());
        setPayPwdDTO.setIdentityNo(userInfo.getIdentityCardNo());
        setPayPwdDTO.setPhone(userInfo.getPhone());
        String backUrl = this.getDomainUrl() + AllinpayNoticeUrl.UPDATE_PAY_PWD;
        // 返回通联url
        String url = allinpayService.updatePayPwd(bizUserId, backUrl, setPayPwdDTO);
        return ServerResponseEntity.success(url);
    }

    @PutMapping("/resetPayPwd")
    @Operation(summary = "重置支付密码", description = "重置支付密码")
    public ServerResponseEntity<String> resetPayPwd(@RequestBody SetPayPwdDTO setPayPwdDTO) {
        String bizUserId = this.getBizUserId(SecurityUtils.getUser().getUserId());
        // 查询用户信息，补充用户姓名和身份证号
        UserInfo userInfo = allinpayService.getUserInfo(bizUserId);
        setPayPwdDTO.setName(userInfo.getName());
        setPayPwdDTO.setIdentityNo(userInfo.getIdentityCardNo());
        setPayPwdDTO.setPhone(userInfo.getPhone());
        String backUrl = this.getDomainUrl() + AllinpayNoticeUrl.RESET_PAY_PWD;
        // 返回通联url
        String url = allinpayService.resetPayPwd(bizUserId, backUrl, setPayPwdDTO);
        return ServerResponseEntity.success(url);
    }

    @PutMapping("/updatePhoneByPayPwd")
    @Operation(summary = "修改绑定手机(返回通联页面url)", description = "仅限个人会员")
    public ServerResponseEntity<String> updatePhoneByPayPwd(@RequestBody UpdatePhoneByPayPwdDTO updatePhoneByPayPwdDTO) {
        String bizUserId = this.getBizUserId(SecurityUtils.getUser().getUserId());
        // 查询用户信息，补充用户姓名和身份证号
        UserInfo userInfo = allinpayService.getUserInfo(bizUserId);
        updatePhoneByPayPwdDTO.setName(userInfo.getName());
        updatePhoneByPayPwdDTO.setIdentityNo(userInfo.getIdentityCardNo());
        updatePhoneByPayPwdDTO.setOldPhone(userInfo.getPhone());
        String backUrl = this.getDomainUrl() + AllinpayNoticeUrl.UPDATE_PHONE_BY_PAY_PWD;
        // 返回通联页面url
        String url = allinpayService.updatePhoneByPayPwd(bizUserId, backUrl, updatePhoneByPayPwdDTO);
        return ServerResponseEntity.success(url);
    }

    @GetMapping("/queryBindAcct")
    @Operation(summary = "查询已绑定的支付账户用户标识", description = "查询已绑定的支付账户用户标识")
    public ServerResponseEntity<QueryBindAcctResp> queryBindAcct() {
        String bizUserId =AuthUserContext.getUserId();
        QueryBindAcctResp resp = allinpayService.queryBindAcct(bizUserId);
        return ServerResponseEntity.success(resp);
    }

    @PostMapping("/signAcctProtocol")
    @Operation(summary = "账户提现协议签约", description = "账户提现协议签约")
    public ServerResponseEntity<String> signAcctProtocol(@RequestBody SignAcctProtocolDTO signAcctProtocolDTO) {
        String bizUserId = this.getBizUserId(SecurityUtils.getUser().getUserId());
        // 查询用户信息，补充用户姓名
        UserInfo userInfo = allinpayService.getUserInfo(bizUserId);
        signAcctProtocolDTO.setSignAcctName(userInfo.getName());
        String backUrl = this.getDomainUrl() + AllinpayNoticeUrl.SIGN_ACCT_PROTOCOL;
        // 请求签约，返回签约地址
        String url = allinpayService.signAcctProtocol(bizUserId, backUrl, signAcctProtocolDTO);
        return ServerResponseEntity.success(url);
    }

    @GetMapping("/signContractQuery")
    @Operation(summary = "账户协议签约查询", description = "账户协议签约查询")
    public ServerResponseEntity<String> signContractQuery(SignAcctProtocolDTO signAcctProtocolDTO) {
        String bizUserId = this.getBizUserId(SecurityUtils.getUser().getUserId());
        String url = allinpayService.signContractQuery(bizUserId, signAcctProtocolDTO);
        return ServerResponseEntity.success(url);
    }

    @PostMapping("/applyBindBankCard")
    @Operation(summary = "请求绑定银行卡", description = "请求绑定银行卡")
    public ServerResponseEntity<ApplyBindBankCardResp> applyBindBankCard(@RequestBody ApplyBankCardDTO applyBankCardDTO) {
        String bizUserId = this.getBizUserId(SecurityUtils.getUser().getUserId());
        // 查询通联用户信息，补充姓名和身份证号
        UserInfo userInfo = allinpayService.getUserInfo(bizUserId);
        applyBankCardDTO.setName(userInfo.getName());
        applyBankCardDTO.setIdentityNo(userInfo.getIdentityCardNo());
        // 请求绑定银行卡
        ApplyBindBankCardResp resp = allinpayService.applyBindBankCard(bizUserId, applyBankCardDTO);
        return ServerResponseEntity.success(resp);
    }

    @PutMapping("/bindBankCard")
    @Operation(summary = "绑定银行卡", description = "绑定银行卡")
    public ServerResponseEntity<Void> bindBankCard(@RequestBody BindBankCardDTO bindBankCardDTO) {
        String bizUserId = this.getBizUserId(SecurityUtils.getUser().getUserId());
        allinpayService.bindBankCard(bizUserId, bindBankCardDTO);
        return ServerResponseEntity.success();
    }

    @PutMapping("/unbindBankCard")
    @Operation(summary = "解绑银行卡", description = "解绑银行卡")
    public ServerResponseEntity<Void> unbindBankCard(@RequestBody UnbindBankCardDTO unbindBankCardDTO) {
        String bizUserId = this.getBizUserId(SecurityUtils.getUser().getUserId());
        allinpayService.unbindBankCard(bizUserId, unbindBankCardDTO);
        return ServerResponseEntity.success();
    }

    @GetMapping("/queryBankCard")
    @Operation(summary = "查询银行卡", description = "查询银行卡")
    @Parameter(name = "cardNo", description = "银行卡号(不传则查询全部银行卡)")
    public ServerResponseEntity<List<BindCard>> queryBankCard(@RequestParam(value = "cardNo", required = false) String cardNo) {
        String bizUserId = this.getBizUserId(SecurityUtils.getUser().getUserId());
        List<BindCard> bindCards = allinpayService.queryBankCard(bizUserId, cardNo);
        return ServerResponseEntity.success(bindCards);
    }

    @PostMapping("/sendVerificationCode")
    @Operation(summary = "发送短信验证码", description = "发送短信验证码")
    public ServerResponseEntity<Void> sendVerificationCode(@RequestBody VerificationCodeDTO verificationCodeDTO) {
        String bizUserId = this.getBizUserId(SecurityUtils.getUser().getUserId());
        allinpayService.sendVerificationCode(bizUserId, verificationCodeDTO);
        return ServerResponseEntity.success();
    }

    @PostMapping("/bindPhone")
    @Operation(summary = "绑定手机", description = "绑定手机")
    public ServerResponseEntity<Void> bindPhone(@RequestBody VerificationCodeDTO verificationCodeDTO) {
        String userId = SecurityUtils.getUser().getUserId();
        String bizUserId = this.getBizUserId(userId);
        // 判断当前用户是否绑定了无感注册的默认手机号，是则先进行解绑
        UserInfo userInfo = allinpayService.getUserInfo(bizUserId);
        if (userInfo.getIsPhoneChecked()
                && Objects.equals(userInfo.getPhone(), AllinpayConstant.DEFAULT_BIND_PHONE_NUMBER)) {
            VerificationCodeDTO unbindDTO = new VerificationCodeDTO();
            unbindDTO.setPhone(AllinpayConstant.DEFAULT_BIND_PHONE_NUMBER);
            allinpayService.unbindPhone(bizUserId, unbindDTO);
        }
        allinpayService.bindPhone(bizUserId, verificationCodeDTO);
        // 并更新用户拓展信息
        UserExtension userExtension = new UserExtension();
        userExtension.setUserId(userId);
        userExtension.setAllinpayPhoneBind(1);
        userExtensionService.updateByUserId(userExtension);
        return ServerResponseEntity.success();
    }

    @PutMapping("/unbindPhone")
    @Operation(summary = "解绑手机", description = "解绑手机")
    public ServerResponseEntity<Void> unbindPhone(@RequestBody VerificationCodeDTO verificationCodeDTO) {
        String bizUserId = this.getBizUserId(SecurityUtils.getUser().getUserId());
        allinpayService.unbindPhone(bizUserId, verificationCodeDTO);
        return ServerResponseEntity.success();
    }

    @PutMapping("/bankCardChangeBindPhone")
    @Operation(summary = "修改绑定手机(银行卡验证版)", description = "修改绑定手机(银行卡验证版)")
    public ServerResponseEntity<BankCardChangeBindPhoneResp> bankCardChangeBindPhone(@RequestBody BankCardChangeBindPhoneDTO bankCardChangeBindPhoneDTO) {
        String bizUserId = this.getBizUserId(SecurityUtils.getUser().getUserId());
        BankCardChangeBindPhoneResp resp = allinpayService.bankCardChangeBindPhone(bizUserId, bankCardChangeBindPhoneDTO);
        return ServerResponseEntity.success(resp);
    }

    @PutMapping("/verifyBankCardChangeBindPhone")
    @Operation(summary = "确认修改绑定手机(银行卡验证版)", description = "确认修改绑定手机(银行卡验证版)")
    public ServerResponseEntity<Void> verifyBankCardChangeBindPhone(@RequestBody VerifyBankCardChangeBindPhoneDTO verifyBankCardChangeBindPhoneDTO) {
        String bizUserId = this.getBizUserId(SecurityUtils.getUser().getUserId());
        allinpayService.verifyBankCardChangeBindPhone(bizUserId, verifyBankCardChangeBindPhoneDTO);
        return ServerResponseEntity.success();
    }

    @PostMapping("/createMember")
    @Operation(summary = "创建会员", description = "创建会员")
    public ServerResponseEntity<Void> createMember() {
        allinpayService.createMember(this.getBizUserId(AuthUserContext.getUserId()), AuthUserContext.getSysType());
        // 更新状态为'已创建'
        userExtensionService.update(new LambdaUpdateWrapper<UserExtension>()
                .set(UserExtension::getAllinpayCreate, 1)
                .eq(UserExtension::getUserId, AuthUserContext.getUserId()));
        return ServerResponseEntity.success();
    }

    @GetMapping("/getBankCardBin")
    @Operation(summary = "查询卡bin", description = "查询卡bin")
    @Parameter(name = "cardNo", description = "卡号")
    public ServerResponseEntity<CardBinInfo> getBankCardBin(String cardNo) {
        CardBinInfo cardBinInfo = allinpayService.getBankCardBin(cardNo);
        return ServerResponseEntity.success(cardBinInfo);
    }

    /**
     * 获取通联平台userId
     * @param userId 用户id
     * @return
     */
    private String getBizUserId(String userId) {
        return AllinpayConstant.USER + userId;
    }

    /**
     * 获取服务器地址
     * @return
     */
    private String getDomainUrl() {
        return shopConfig.getDomain().getApiDomainName();
    }
}
